package sun.scheduler.io;

import sun.scheduler.core.resource.Resource;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.File;

import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;

import sun.scheduler.core.*;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.security.acl.LastOwnerException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Hashtable;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import sun.scheduler.core.job.*;
import sun.scheduler.core.resource.Resource;
import sun.scheduler.core.resource.ResourceInfo;

/**
 * Class to parse a file and read job info and create an array list with jobs.
 */
public class ScheduleReader {

    /**
     * last read resource an job file
     */
    private static String lastResourceFile, lastJobFile;
    private static Date startDate;

    /**
     * Reads a ~jobs.csv-file and creates an array list with Job elements
     *
     * @param fileName - Name of the job file
     * @return jobs - ArrayList with jobs
     * @throws ParseException
     */
    public static ArrayList<Job> readJobsFromFile(ArrayList<Resource> res,String fileName)
            throws ParseException {

        lastJobFile = fileName;


        BufferedReader reader = null;
        FileReader fr = null;
        ArrayList<Job> jobs = new ArrayList<Job>();
        Resource resource = null;
        try {
            fr = new FileReader(fileName);
            reader = new BufferedReader(fr);

            // skip first line
            if (reader.ready()) {
                reader.readLine();
            }

            while (reader.ready()) {

                ArrayList<String> attributs = new ArrayList<String>();
                String[] jobStrArray, fieldStrArray;
                boolean gaenseFuesschen = false;
                int jobId, groupId;
                String jobName, groupName, resourceName;
                String line = reader.readLine().trim();
                jobStrArray = line.split("\"");
                for (int k = 0; k < jobStrArray.length; k++) {
                    if (jobStrArray[k].startsWith(";")) {
                        jobStrArray[k] = jobStrArray[k].substring(1,
                                jobStrArray[k].length());
                    }
                    if (jobStrArray[k].endsWith(";")) {
                        jobStrArray[k] = jobStrArray[k].substring(0,
                                jobStrArray[k].length() - 1);
                    }
                }

                for (int i = 0; i < jobStrArray.length; i++) // single entry per field
                {
                    if (!gaenseFuesschen) {
                        fieldStrArray = jobStrArray[i].split(";");

                        attributs.addAll(Arrays.asList(fieldStrArray));
                        gaenseFuesschen = true;
                    } // multiple entries per field
                    else {
                        attributs.add(jobStrArray[i]);
                        gaenseFuesschen = false;
                    }
                }

                // create Job and add it to ArrayList jobs
                jobId = Integer.parseInt(attributs.get(0));
                groupId = Integer.parseInt(attributs.get(2));
                groupName = attributs.get(3);
                jobName = attributs.get(4);
                resourceName = attributs.get(5);
                ArrayList<Integer> startsWith = new ArrayList<Integer>();
                SimpleDateFormat startSdf, endSdf;
                boolean fixedStart, chained;


                // setStartDate
                if (attributs.get(6).length() == 16) {
                    startSdf = new SimpleDateFormat("dd.MM.yyyy HH:mm");
                } else if (attributs.get(6).length() == 10) {
                    startSdf = new SimpleDateFormat("dd.MM.yyyy");
                } else if (attributs.get(6).length() == 0) {
                    startSdf = null;
                } else {
                    throw new IllegalArgumentException(
                            "Startdate-Format is not correct!");
                }
                
                
                
                startDate = startSdf.parse(attributs.get(6));

                // setEnd
                if (attributs.get(7).length() == 16) {
                    endSdf = new SimpleDateFormat("DD.MM.yyyy HH:mm");
                    endSdf.parse(attributs.get(7));
                } else if (attributs.get(7).length() == 10) {
                    endSdf = new SimpleDateFormat("DD.MM.yyyy");
                    endSdf.parse(attributs.get(7));
                } else if (attributs.get(7).length() == 0) {
                    endSdf = null;
                } else {
                    throw new IllegalArgumentException(
                            "Enddate-Format is not correct!");
                }

                // setWork (benötigt?)
                int work = Integer.parseInt(attributs.get(8));

                // setInitRes
                int initRes = (Integer.parseInt(attributs.get(9)));

                // setMinRes
                int minRes = (Integer.parseInt(attributs.get(10)));

                // setMaxRes
                int maxRes = (Integer.parseInt(attributs.get(11)));

                for (Resource ress : res) {
                    String vglName = ress.info.name;
                    if (vglName.replace("\"", "").equals(resourceName)) resource = ress;
                }

                Job jobi = new Job(jobId, groupId, jobName, groupName, minRes, maxRes, initRes, work, resource);

                // PREDS
                if (!attributs.get(1).equals("")) {
                    String[] strpred = attributs.get(1).split(";");
                    for (int i = 0; i < strpred.length; i++) {
                        jobi.addPredecessor(Integer.parseInt(strpred[i]));
                    }
                }
                // setFixedStart (nicht benötigt)
                fixedStart = false;
                if (!attributs.get(12).equals("n")) {
                    fixedStart = true;
                }

                // setParallelJobs
                if (!attributs.get(13).equals("")) {
                    String[] strparals = attributs.get(13).split(";");
                    for (int i = 0; i < strparals.length; i++) {
                        //System.out.println(strparals[i]);
                        jobi.addParallelJob(Integer.parseInt(strparals[i]));
                    }
                }


                // setChained
                chained = false;
                if (attributs.get(14).equals("n")) {
                    chained = true;
                }

                // setNotParallelJobs (nicht benötigt!)
                if (!attributs.get(15).equals("")) {
                    String[] strparals = attributs.get(15).split(";");
//                    for (int i = 0; i < strparals.length; i++)
//                        job.addNotParallel(Integer.parseInt(strparals[i]));
                }

                // setStartsWith
                if (!attributs.get(16).equals("")) {
                    String[] strStartsWith = attributs.get(16).split(";");
                    for (int i = 0; i < strStartsWith.length; i++) {
                        startsWith.add(Integer.parseInt(strStartsWith[i]));
                    }
                }

                jobs.add(jobi);
            }

        } catch (FileNotFoundException e) {
            //_warnMessageReadJobFile(e);
            System.err.println("File " + fileName + " not found!");
            //e.printStackTrace();
        } catch (IOException e) {
            //_warnMessageReadJobFile(e);
            System.err.println("Error while reading: " + fileName + "!");
            //e.printStackTrace();
        } catch (IllegalArgumentException e) {
            //_warnMessageReadJobFile(e);
            System.err.println("Error while reading: " + fileName + "!");
            //e.printStackTrace();
        } finally {
            try {
                reader.close();
                fr.close();

            } catch (IOException e) {
                _warnMessageReadJobFile(e);
                System.err.println("Error while reading: " + fileName + "!");
                e.printStackTrace();

            }

        }

        return jobs;
    }

    /**
     * Method to read a ~res.cvs file and parse it to a program
     *
     * @param filename - name of the resource file
     */
    public static ArrayList<Resource> readResourcesFromFile(String fileName)
            throws ParseException {

        lastResourceFile = fileName;
        BufferedReader reader = null;
        FileReader fr = null;
        ArrayList<Resource> resources = new ArrayList<Resource>();
        try {
            fr = new FileReader(fileName);
            reader = new BufferedReader(fr);

            // skip first line
            if (reader.ready()) {
                reader.readLine();
            }

            while (reader.ready()) {
                String[] resStr = reader.readLine().split(";");
                String resName = resStr[0];
                String resModel = resStr[2];
                int resId = Integer.parseInt(resStr[1]);


//                // setResOffset
//                res.setResOffset(resStr[3].equals("1")
//                        || resStr[3].equals("ja"));

                // setMaxCapacity
                int maxCap = (Integer.parseInt(resStr[4]));

                // setResSalary
                double ppT = (Double.parseDouble(resStr[5]));

                // setFactor
                double aspectRatio = (Double.parseDouble(resStr[6]));


                ResourceInfo resInfo = new ResourceInfo(resId, resModel, resName);
                Resource res = new Resource(maxCap, ppT, aspectRatio, resInfo);

                resources.add(res);
            }

        } catch (FileNotFoundException e) {
            //_warnMessageReadResourceFile(e);
            System.err.println("File " + fileName + " not found!");
            e.printStackTrace();
        } catch (IOException e) {
            //_warnMessageReadResourceFile(e);
            System.err.println("Error while reading: " + fileName + "!");
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            //_warnMessageReadResourceFile(e);
            System.err.println("Error while reading: " + fileName + "!");
            e.printStackTrace();
        } finally {
            try {
                reader.close();
                fr.close();

            } catch (IOException e) {
                //_warnMessageReadResourceFile(e);
                System.err.println("Error while reading: " + fileName + "!");
                e.printStackTrace();
                // /TODO handle this

            }
        }
        return resources;
    }

    /**
     * @return the lastResourceFile
     */
    public static String getLastResourceFile() {
        return lastResourceFile;
    }

    /**
     * @return the lastJobFile
     */
    public static String getLastJobFile() {
        return lastJobFile;
    }

    /**
     * Method to return a resource hashtable (not needed anymore!)
     */
    public static Hashtable<String, Resource> getResHashTable(ArrayList<Resource> resArray) {
        Hashtable<String, Resource> ht = null;
        for (Resource r : resArray) {
            ht.put(r.info.name, r);
        }

        return ht;
    }
    
    /**
     * Method to open a file-chooser and read the jobs from a chosen file
     *
     */
    public static ArrayList<Job> readFileJobs(ArrayList<Resource> resses) {
        ArrayList<Job> jobs = null;
        JFileChooser fc = new JFileChooser();
        fc.setDialogTitle("Choose a JOB file...");
        fc.setFileFilter(new FileFilter() {

            public String getDescription() {
                return "job-File(*.csv)";
            }

            public boolean accept(File f) {
                return f.getName().toLowerCase().endsWith(".csv")
                        || f.isDirectory();

            }
        });
        int res = fc.showOpenDialog(null);
        if (res == JFileChooser.APPROVE_OPTION) {
            try {
                jobs = ScheduleReader.readJobsFromFile(resses,fc.getSelectedFile().getAbsolutePath());

                return jobs;
            } catch (Exception e) {
                _warnMessageReadJobFile(e);
                e.printStackTrace();
            }
        }
        return jobs;
    }

    
    /**
     * Method to open a file-chooser and read the resources from a chosen file
     *
     */
    public static ArrayList<Resource> readFileResources() {
        ArrayList<Resource> resources = null;
        JFileChooser fc = new JFileChooser();
        fc.setDialogTitle("Choose a RESOURCE file...");
        fc.setFileFilter(new FileFilter() {

            public String getDescription() {
                return "resource-File(*.csv)";
            }

            public boolean accept(File f) {
                return f.getName().toLowerCase().endsWith(".csv")
                        || f.isDirectory();

            }
        });
        int res = fc.showOpenDialog(null);
        if (res == JFileChooser.APPROVE_OPTION) {
            try {
                resources = ScheduleReader.readResourcesFromFile(fc.getSelectedFile().getAbsolutePath());

                return resources;
            } catch (Exception e) {
                _warnMessageReadResourceFile(e);
                e.printStackTrace();
            }
        }
        return resources;
    }

    
    /**
     * Method to test whether the file is a JOB.csv file
     * 
     * @param fileName - file to test
     * @return true if it is, false otherwise
     * @throws ParseException 
     */
    public static boolean isJobFile(String fileName) throws ParseException {
        BufferedReader reader = null;
        FileReader fr = null;
        try {
            fr = new FileReader(fileName);
            reader = new BufferedReader(fr);

            // skip first line
            if (reader.ready()) {
                reader.readLine();
            }

            while (reader.ready()) {

                ArrayList<String> attributs = new ArrayList<String>();
                String[] jobStrArray, fieldStrArray;
                boolean gaenseFuesschen = false;
                int jobId, groupId;
                String jobName, groupName, resourceName;
                String line = reader.readLine().trim();
                jobStrArray = line.split("\"");
                for (int k = 0; k < jobStrArray.length; k++) {
                    if (jobStrArray[k].startsWith(";")) {
                        jobStrArray[k] = jobStrArray[k].substring(1,
                                jobStrArray[k].length());
                    }
                    if (jobStrArray[k].endsWith(";")) {
                        jobStrArray[k] = jobStrArray[k].substring(0,
                                jobStrArray[k].length() - 1);
                    }
                }

                for (int i = 0; i < jobStrArray.length; i++) // single entry per field
                {
                    if (!gaenseFuesschen) {
                        fieldStrArray = jobStrArray[i].split(";");

                        attributs.addAll(Arrays.asList(fieldStrArray));
                        gaenseFuesschen = true;
                    } // multiple entries per field
                    else {
                        attributs.add(jobStrArray[i]);
                        gaenseFuesschen = false;
                    }
                }

                // create Job and add it to ArrayList jobs
                jobId = Integer.parseInt(attributs.get(0));
                groupId = Integer.parseInt(attributs.get(2));
                groupName = attributs.get(3);
                jobName = attributs.get(4);
                resourceName = attributs.get(5);
                ArrayList<Integer> startsWith = new ArrayList<Integer>();
                SimpleDateFormat startSdf, endSdf;
                boolean fixedStart, chained;


                // setStartDate
                if (attributs.get(6).length() == 16) {
                    startSdf = new SimpleDateFormat("dd.MM.yyyy HH:mm");
                } else if (attributs.get(6).length() == 10) {
                    startSdf = new SimpleDateFormat("dd.MM.yyyy");
                } else if (attributs.get(6).length() == 0) {
                    startSdf = null;
                } else {
                    throw new IllegalArgumentException(
                            "Startdate-Format is not correct!");
                }

                // setEnd
                if (attributs.get(7).length() == 16) {
                    endSdf = new SimpleDateFormat("DD.MM.yyyy HH:mm");
                    endSdf.parse(attributs.get(7));
                } else if (attributs.get(7).length() == 10) {
                    endSdf = new SimpleDateFormat("DD.MM.yyyy");
                    endSdf.parse(attributs.get(7));
                } else if (attributs.get(7).length() == 0) {
                    endSdf = null;
                } else {
                    throw new IllegalArgumentException(
                            "Enddate-Format is not correct!");
                }

                // setWork (benötigt?)
                int work = Integer.parseInt(attributs.get(8));

                // setInitRes
                int initRes = (Integer.parseInt(attributs.get(9)));

                // setMinRes
                int minRes = (Integer.parseInt(attributs.get(10)));

                // setMaxRes
                int maxRes = (Integer.parseInt(attributs.get(11)));

                // PREDS
                if (!attributs.get(1).equals("")) {
                    String[] strpred = attributs.get(1).split(";");
                    for (int i = 0; i < strpred.length; i++) {
                        Integer.parseInt(strpred[i]);
                    }
                }
                // setFixedStart (nicht benötigt)
                fixedStart = false;
                if (!attributs.get(12).equals("n")) {
                    fixedStart = true;
                }

                //  setParallelJobs
                if (!attributs.get(13).equals("")) {
                    String[] strparals = attributs.get(13).split(";");
                    for (int i = 0; i < strparals.length; i++) {
                      Integer.parseInt(strparals[i]);
                    }
                }


                // setChained
                chained = false;
                if (attributs.get(14).equals("n")) {
                    chained = true;
                }

                // setNotParallelJobs (nicht benötigt!)
                if (!attributs.get(15).equals("")) {
                    String[] strparals = attributs.get(15).split(";");
                }

                // setStartsWith
                if (!attributs.get(16).equals("")) {
                    String[] strStartsWith = attributs.get(16).split(";");
                    for (int i = 0; i < strStartsWith.length; i++) {
                        startsWith.add(Integer.parseInt(strStartsWith[i]));
                    }
                }
            }

        } catch (FileNotFoundException e) {
            //_warnMessageReadJobFile(e);
            System.err.println("File " + fileName + " not found!");
            //e.printStackTrace();
            return false;
        } catch (IOException e) {
            //_warnMessageReadJobFile(e);
            System.err.println("Error while reading: " + fileName + "!");
            //e.printStackTrace();
            return false;
        } catch (IllegalArgumentException e) {
            //_warnMessageReadJobFile(e);
            System.err.println("Error while reading: " + fileName + "!");
            //e.printStackTrace();
            return false;
        } finally {
            try {
                reader.close();
                fr.close();

            } catch (IOException e) {
                _warnMessageReadJobFile(e);
                System.err.println("Error while reading: " + fileName + "!");
                e.printStackTrace();
                return false;

            }

        }
        return true;
    }
    
    public static Date getStartDate() {
        return startDate;
    }

    private static void _warnMessageReadJobFile(Exception e) {
        String warnMessage = "<html>"
                + "<b><font size=\"6\">Oooooops!!!!!!!!</font><br></br> That should not have happened! </b></html> "
                + "\nAn Error occured while parsing the JOB file! \n Please try again or contact the SUN support 0800 - 12345678."
                + "\n\n\n"
                + "<html><b>Error:</b></html>\n\b\b" + e.toString();
        JOptionPane op = new JOptionPane();
        op.showMessageDialog(op, warnMessage, "Ooops... Something went entirely wrong there!", JOptionPane.ERROR_MESSAGE);
    }

    private static void _warnMessageReadResourceFile(Exception e) {
        String warnMessage = "<html>"
                + "<b><font size=\"6\">Oooooops!!!!!!!!</font><br></br> That should not have happened! </b></html> "
                + "\nAn Error occured while parsing the RESOURCE file! \n Please try again or contact the SUN support 0800 - 12345678."
                + "\n\n\n"
                + "<html><b>Error:</b></html>\n\b\b" + e.toString();
        JOptionPane op = new JOptionPane();
        op.showMessageDialog(op, warnMessage, "Ooops... Something went entirely wrong there!", JOptionPane.ERROR_MESSAGE);
    }

    private static void _warnMessageReadFile(Exception e) {
        String warnMessage = "<html>"
                + "<b><font size=\"6\">Oooooops!!!!!!!!</font><br></br> That should not have happened! </b></html> "
                + "\nAn Error occured while parsing the files! \n Please try again or contact the SUN support 0800 - 12345678."
                + "\n\n\n"
                + "<html><b>Error:</b></html>\n\b\b" + e.toString();
        JOptionPane op = new JOptionPane();
        op.showMessageDialog(op, warnMessage, "Ooops... Something went entirely wrong there!", JOptionPane.ERROR_MESSAGE);
    }

    private static void _warnMessage(Exception e) {
        String warnMessage = "<html>"
                + "<b><font size=\"6\">Oooooops!!!!!!!!</font><br></br> That should not have happened! </b></html> "
                + "\nAn Error occured! \n Please try again or contact the SUN support 0800 - 12345678."
                + "\n\n\n"
                + "<html><b>Error:</b></html>\n\b\b" + e.toString();
        JOptionPane op = new JOptionPane();
        op.showMessageDialog(op, warnMessage, "Ooops... Something went entirely wrong there!", JOptionPane.ERROR_MESSAGE);
    }
}
